import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.logging.Logger;

import com.quantanetwork.esm.port.IdenifyMethodFactory;
import com.quantanetwork.esm.port.IdentifyMethod;
import com.quantanetwork.esm.port.QuantaThreadPool;
import com.quantanetwork.esm.port.Result;

/**
* Company: QuantaNetwork BeiJing Ltd
* Author : 张彦龙
* DateTime: Nov 25, 2008  4:05:56 PM
*/
public class ScanPort implements Callable<Result>
{
	public static Logger logger = Logger.getLogger(ScanPort.class.getName());
	private String host;
	private int startPort;
	private int endPort;
	private int timeOut;
	private int maxUDP;
	private String message = "help^M^J";

	public ScanPort(String h, int sp, int ep, int timeOut, int maxUDP)
	{
		super();
		host = h;
		startPort = sp;
		endPort = ep;
		this.timeOut = timeOut;
		this.maxUDP = maxUDP;
	}

	public Result call()
	{
		Result result = new Result();
		long start = System.currentTimeMillis();
		for (int i = startPort; i <= endPort; i++)
		{
			try
			{
				boolean alive = false;
				Socket s = null;
				try
				{
					s = new Socket();
					s.connect(new InetSocketAddress(host, i), timeOut);
					if (s.isConnected())
					{
						alive = true;
					}
				}
				catch (Exception e)
				{
				}
				finally
				{
					try
					{
						if (s != null)
						{
							s.close();
						}
					}
					catch (Exception e)
					{
					}
				}
				if (i <= maxUDP)
				{
					DatagramSocket socket = null;
					try
					{
						socket = new DatagramSocket();
						socket.setSoTimeout(timeOut);
						socket.setTrafficClass(0x10);
						socket.connect(new InetSocketAddress(host, i));
						if (socket.isConnected())
						{
							alive = true;
							socket.disconnect();
						}
					}
					catch (Exception e)
					{
						e.printStackTrace();
					}
					finally
					{
						try
						{
							if (socket != null)
							{
								socket.close();
							}
						}
						catch (Exception e)
						{
						}
					}
				}
				if (alive)
				{
					IdentifyMethod method = IdenifyMethodFactory.getIndentify(i);
					if (method != null)
					{
					}
					else
					{
						try
						{
							File file = new File("etc/services.lst");
							synchronized (file)
							{
								FileInputStream fileInputStream = new FileInputStream(file);
								BufferedReader br = new BufferedReader(new InputStreamReader(fileInputStream));
								String line = null;
								boolean flag = false;
								while ((line = br.readLine()) != null)
								{
									if (line.indexOf(i + "/tcp") > 0)
									{
										flag = true;
										break;
									}
								}
								fileInputStream.close();
								if (flag)
								{
									String portInfo = "";
									if (!line.substring(10, 34).trim().equals(""))
									{
										portInfo += "可能端口名称:" + line.substring(10, 34).trim();
									}
									if (!line.substring(34).trim().equals(""))
									{
										portInfo += "描述:" + line.substring(34).trim();
									}
									if (!portInfo.equals(""))
									{
										logger.info(portInfo);
									}
								}
							}
						}
						catch (Exception e)
						{
							logger.info(e.getMessage());
						}
					}
					if (alive)
					{
						logger.info("主机：" + host + " 端口：" + i + "开启");
					}
				}
			}
			catch (Exception e)
			{
			}
		}
		result.setInfo("Port From:" + startPort + "  TO:" + endPort + "Scan Complete");
		result.setTime(System.currentTimeMillis() - start);
		return result;
	}

	public String getHost()
	{
		return host;
	}

	public void setHost(String host)
	{
		this.host = host;
	}

	public int getStartPort()
	{
		return startPort;
	}

	public void setStartPort(int startPort)
	{
		this.startPort = startPort;
	}

	public int getEndPort()
	{
		return endPort;
	}

	public void setEndPort(int endPort)
	{
		this.endPort = endPort;
	}

	public int getTimeOut()
	{
		return timeOut;
	}

	public void setTimeOut(int timeOut)
	{
		this.timeOut = timeOut;
	}

	public static void main(String[] args)
	{
		int maxUdp = 10000;
		String host = "192.168.1.3";
		int startPort = 0;
		int endPort = 65535;
		//单词采集超时时间
		int timeOut = 2000;
		for (int i = 1; i <= 100; i++)
		{
			//每个任务内从0到100个端口，超时时间2秒
			TestSacnForBetterWay(host, startPort, endPort, i, timeOut, maxUdp);
		}
		System.exit(0);
	}

	public static void TestSacnForBetterWay(String host, int startPort, int endPort, int taskNum, int timeOut, int maxUdp)
	{
		long start = System.currentTimeMillis();
		int threadCount = 0;
		ThreadPoolExecutor executorService = (ThreadPoolExecutor) QuantaThreadPool.newFixedThreadPool(500);
		ExecutorCompletionService<Result> service = new ExecutorCompletionService<Result>(executorService);
		while (startPort < endPort)
		{
			if ((startPort + taskNum) >= endPort)
			{
				service.submit(new ScanPort(host, startPort + 1, endPort, timeOut, maxUdp));
			}
			else
			{
				service.submit(new ScanPort(host, startPort + 1, startPort + taskNum, timeOut, maxUdp));
			}
			threadCount++;
			startPort += taskNum;
		}
		long totalTime = 0l;
		int tempThreadCount = threadCount * 1000;
		try
		{
			while (threadCount > 0)
			{
				Future<Result> future = service.take();
				totalTime += future.get().getTime();
				threadCount--;
			}
		}
		catch (Exception e)
		{
		}
		executorService.shutdown();
		logger.info("端口数量" + (endPort - startPort) + " 超时时间 " + timeOut + " 平均任务时间:" + (totalTime / tempThreadCount) + "毫秒");
		logger.info("任务描述:  端口总数 " + (endPort - startPort) + " 超时时间" + timeOut + ",运行时间:" + (System.currentTimeMillis() - start) / 1000 + "秒");
	}

	public static void TheadCreateCheck(int threadNum)
	{
		//操作系统CPU数量
		int cpus = Runtime.getRuntime().availableProcessors();
		System.out.println(cpus);
		//操作系统内存信息
	}
}
